﻿using CPPEI.ETL.DataServiceInterface;
using CPPEI.ETL.Infrastructure;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml;

namespace CPPEI.ETL.DSImplement
{
    public class WSDataServiceProxy : IDataServiceProxy
    {
        private static string s_dataServiceDataCacheDirectory;
        public static string DataServiceDataCacheDirectory
        {
            get
            {
                if (string.IsNullOrEmpty(s_dataServiceDataCacheDirectory))
                {
                    s_dataServiceDataCacheDirectory = System.Configuration.ConfigurationManager.AppSettings["DataService.Data.CacheDirectory"];
                    if(System.IO.Directory.Exists(s_dataServiceDataCacheDirectory) == false)
                    {
                        System.IO.Directory.CreateDirectory(s_dataServiceDataCacheDirectory);
                    }
                }
                if (string.IsNullOrEmpty(s_dataServiceDataCacheDirectory))
                {
                    s_dataServiceDataCacheDirectory = string.Format("{0}\\DataServiceCache\\",
                    System.Configuration.ConfigurationManager.AppSettings["LogDirectory"]);
                    if (System.IO.Directory.Exists(s_dataServiceDataCacheDirectory) == false)
                    {
                        System.IO.Directory.CreateDirectory(s_dataServiceDataCacheDirectory);
                    }
                }
                return s_dataServiceDataCacheDirectory;
            }
        }
        public TDataService GetSchema(DataServiceInfo info)
        {
            Type type = WSTool.CreateAndLoadWSClientType(info);


            TDataService tDataSource = new TDataService();
            tDataSource.Name = type.Name;


            MethodInfo[] methods = type.GetMethods();
            foreach (var method in methods)
            {
                if(method.DeclaringType == type && method.CustomAttributes.Count() > 0)
                {
                    TDataSource tDataSet = new TDataSource();
                    tDataSet.Name = method.Name;
                    tDataSet.Value = method.Name;
                    tDataSet.Type = "Method";

                    ParameterInfo[] parameters = method.GetParameters();
                    foreach (var @param in parameters)
                    {
                        WSTypeUtil.ConvertToParameters(tDataSet, string.Empty, @param.Name, @param.ParameterType);
                    }

                    if (method.ReturnParameter != null)
                    {
                        //检查数据类型是否支持
                        if (WSTypeUtil.IsSupportResultType(method.ReturnParameter.ParameterType) == false)
                        {
                            throw new WS.WSNotSupportException();
                        }

                        List<Column> columns = null;

                        if (method.ReturnParameter.ParameterType == typeof(string) ||
                            !method.ReturnParameter.ParameterType.IsClass)
                        {
                            columns = ValueData.GetColumns(method.ReturnParameter.ParameterType);
                        }
                        else
                        {
                            string rootPath = null;
                            Type elementType = null;
                           
                            if (method.ReturnParameter.ParameterType != typeof(DataSet)
                                && method.ReturnParameter.ParameterType != typeof(DataTable)
                                && method.ReturnParameter.ParameterType != typeof(XmlNode)
                                && method.ReturnParameter.ParameterType != typeof(XmlElement))
                            {
                                if (WSTypeUtil.IsArrayObjectResult("RESULT", method.ReturnParameter.ParameterType, out rootPath, out elementType))
                                {
                                    columns = CPPEI.ETL.DSImplement.WS.ArrayData.GetColumns(elementType, rootPath);
                                }
                                else
                                {
                                    columns = ObjectData.GetColumns(method.ReturnParameter.ParameterType);
                                }
                            }
                        }

                        tDataSet.Columns = new List<TDataSourceColumn>();
                        if(columns!=null)
                        {
                            for (int index = 0; index < columns.Count; index++)
                            {
                                tDataSet.Columns.Add(new TDataSourceColumn(columns[index].Name, columns[index].Type));
                            }
                        }
                    }

                    tDataSource.DataSources.Add(tDataSet);
                }
            }
            return tDataSource;
        }

        public TDataSource GetSchema(DataSourceInfo info)
        {
            return null;
        }

        public IData GetData(DataSourceInfo info, Dictionary<string, object> args)
        {
            object returnValue = WSTool.InvokeWebService(info, args);

            if (returnValue != null)
            {
                if (returnValue.GetType() == typeof(string) || !returnValue.GetType().IsClass)
                {
                    return new ValueData(returnValue);
                }
                else if (returnValue.GetType() == typeof(XmlNode)
                    || returnValue.GetType() == typeof(XmlElement))
                {
                    // 记录缓存数据文件
                    try
                    {
                        string dataCacheFile = string.Format("{0}{1}-{2}.xml", DataServiceDataCacheDirectory, DateTime.Now.ToString("yyyyMMddhhmmss"), info.DataSourceValue);

                        System.IO.File.WriteAllText(dataCacheFile, ((XmlNode)returnValue).OuterXml);
                    }
                    catch
                    {

                    }

                    return new CPPEI.ETL.DSImplement.WS.XmlNodeData((XmlNode)returnValue);
                }
                else if (returnValue.GetType() == typeof(DataTable))
                {
                    return new DataTableData((DataTable)returnValue);
                }
                else if(returnValue.GetType() == typeof(DataSet))
                {
                    DataSet  dataSet = (DataSet)returnValue;
                    if(dataSet.Tables == null || dataSet.Tables.Count == 0)
                    {
                        return null;
                    }
                    return new DataTableData(dataSet.Tables[0]);
                }
                else
                {
                    string rootPath = null;
                    Type elementType = null;
                    if (WSTypeUtil.IsArrayObjectResult("RESULT", returnValue.GetType(), out rootPath, out elementType))
                    {
                        return new CPPEI.ETL.DSImplement.WS.ArrayData(returnValue, rootPath);
                    }
                    else
                    {
                        return new ObjectData(returnValue);
                    }
                }
            }
            return null;
        }

        public List<string> Enumerate(DataServiceInterface.DataServiceInfo info)
        {
            return null;
        }

        public List<TDataSourceColumn> GetSoapHeaderColumns(DataServiceInfo info)
        {
            Type type = WSTool.LoadWSClientType(info);
            return null;
        }
    }
}
